home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************
- * Row.c: Methods for the Row widget
- * From:
- * The X Window System,
- * Programming and Applications with Xt
- * OSF/Motif Edition
- * by
- * Douglas Young
- * Prentice Hall, 1990
- *
- * Example described on pages: 375-390
- *
- * Modified slightly by Chris Fouts, Silicon Graphics, Inc. 1994
- *
- * Copyright 1989 by Prentice Hall
- * All Rights Reserved
- *
- * This code is based on the OSF/Motif widget set and the X Window System
- *
- * Permission to use, copy, modify, and distribute this software for
- * any purpose and without fee is hereby granted, provided that the above
- * copyright notice appear in all copies and that both the copyright notice
- * and this permission notice appear in supporting documentation.
- *
- * Prentice Hall and the author disclaim all warranties with regard to
- * this software, including all implied warranties of merchantability and
- * fitness. In no event shall Prentice Hall or the author be liable for any
- * special, indirect or cosequential damages or any damages whatsoever
- * resulting from loss of use, data or profits, whether in an action of
- * contract, negligence or other tortious action, arising out of or in
- * connection with the use or performance of this software.
- *
- * Open Software Foundation is a trademark of The Open Software Foundation, Inc.
- * OSF is a trademark of Open Software Foundation, Inc.
- * OSF/Motif is a trademark of Open Software Foundation, Inc.
- * Motif is a trademark of Open Software Foundation, Inc.
- * DEC is a registered trademark of Digital Equipment Corporation
- * HP is a registered trademark of the Hewlett Packard Company
- * DIGITAL is a registered trademark of Digital Equipment Corporation
- * X Window System is a trademark of the Massachusetts Institute of Technology
- ******************************************************************************/
-
-
- #include <stdio.h>
- #include <X11/IntrinsicP.h>
- #include <X11/Intrinsic.h>
- #include <X11/Composite.h>
- #include <X11/CompositeP.h>
- #include <X11/Xm/XmStrDefs.h>
- #include "RowP.h"
- #include "Row.h"
- #define MAX(a,b) ((a) > (b) ? (a) : (b))
- #define MIN(a,b) ((a) < (b) ? (a) : (b))
-
- /* BEGIN PROTOTYPES -S Row.c */
- static void ChangeManaged( Widget w ) ;
- static void do_layout( XsRowWidget parent ) ;
- static XtGeometryResult GeometryManager( Widget w,
- XtWidgetGeometry *request,
- XtWidgetGeometry *reply ) ;
- static void Initialize( Widget request, Widget new,
- ArgList args, Cardinal *numArgs ) ;
- static XtGeometryResult PreferredSize( Widget w,
- XtWidgetGeometry *request,
- XtWidgetGeometry *preferred ) ;
- static void Resize( Widget w ) ;
- static XtGeometryResult try_layout( XsRowWidget parent, Mask *mask,
- Dimension *w_delta, Dimension *h_delta ) ;
- /* END PROTOTYPES -S Row.c */
-
- static XtResource resources[] =
- {
- { XmNspacing, XmCSpacing, XtRInt, sizeof( int ),
- XtOffset( XsRowWidget, row.spacing ), XtRString, "5" },
- } ;
-
-
- XsRowClassRec XsrowClassRec = {
- {
- /* core_class members */
- (WidgetClass) &compositeClassRec, /* superclass */
- "Row", /* class_name */
- sizeof(XsRowRec), /* widget_size */
- NULL, /* class_initialize */
- NULL, /* class_part_init */
- FALSE, /* class_inited */
- Initialize, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber( resources ), /* num_resources */
- NULLQUARK, /* xrm_class */
- TRUE, /* compress_motion */
- TRUE, /* compress_exposure */
- TRUE, /* compress_enterleave*/
- FALSE, /* visible_interest */
- NULL, /* destroy */
- Resize, /* resize */
- NULL, /* expose */
- NULL, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- PreferredSize, /* query_geometry */
- NULL, /* display_accelerator*/
- NULL, /* extension */
- },
- {
- /* composite_class members */
- GeometryManager, /* geometry_manager */
- ChangeManaged, /* change_managed */
- XtInheritInsertChild, /* insert_child */
- XtInheritDeleteChild, /* delete_child */
- NULL, /* extension */
- },
- {
- /* Row class members */
- 0, /* empty */
- }
- };
-
-
- WidgetClass xsRowWidgetClass = (WidgetClass) &XsrowClassRec;
-
-
- static void
- Initialize(
- Widget request,
- Widget new,
- ArgList args,
- Cardinal *numArgs
- )
- {
- XsRowWidget reqRow = (XsRowWidget)request ;
- XsRowWidget newRow = (XsRowWidget)new ;
-
- if( reqRow->core.width <= 0 )
- {
- newRow->core.width = 5 ;
- }
- if( reqRow->core.height <= 0 )
- {
- newRow->core.height = 5 ;
- }
- if( reqRow->row.spacing < 0 )
- {
- newRow->row.spacing = 5 ;
- }
- }
-
-
-
- static void
- Resize(
- Widget w
- )
- {
- do_layout( (XsRowWidget)w ) ;
- }
-
-
-
- static void
- do_layout(
- XsRowWidget parent
- )
- {
- Widget child ;
- int i ;
- Dimension childwidth = 2 * parent->row.spacing ;
- Position xpos = parent->row.spacing ;
- Dimension pad = 0 ;
- int n_managed_children = 0 ;
-
- /*
- * Compute the total width of all managed children and
- * determine how many children are managed.
- */
- for( i = 0 ; i < parent->composite.num_children ; i++ )
- {
- child = parent->composite.children[i] ;
- if( child->core.managed )
- {
- n_managed_children++;
- childwidth += child->core.width +
- child->core.border_width * 2 ;
- }
- }
- /*
- * Divide any remaining space by the number
- * of children.
- */
- if( ( n_managed_children > 1 ) && ( parent->core.width > childwidth ) )
- {
- pad = ( parent->core.width - childwidth ) /
- ( n_managed_children - 1 ) ;
- }
- /*
- * Position all children.
- */
- for( i = 0 ; i < parent->composite.num_children ; i++ )
- {
- child = parent->composite.children[i] ;
- if( child->core.managed )
- {
- XtMoveWidget( child, xpos, parent->row.spacing ) ;
- xpos += pad + child->core.width +
- child->core.border_width * 2 ;
- }
- }
- }
-
-
-
- static XtGeometryResult
- PreferredSize(
- Widget w,
- XtWidgetGeometry *request,
- XtWidgetGeometry *preferred
- )
- {
- XsRowWidget row = (XsRowWidget)w ;
- Widget child ;
- int i ;
-
- /*
- * If no changes are being made to width or
- * height, just agree.
- */
- if( !( request->request_mode & CWWidth ) &&
- !( request->request_mode & CWHeight ) )
- {
- return( XtGeometryYes ) ;
- }
-
- /*
- * Calculate our minimum size.
- */
- preferred->width = row->row.spacing ;
- preferred->height = 0 ;
- for( i = 0 ; i < row->composite.num_children; i++ )
- {
- child = row->composite.children[i] ;
- if( child->core.managed )
- {
- Dimension h ;
-
- preferred->width += child->core.width +
- child->core.border_width * 2 +
- row->row.spacing ;
- h = child->core.height + child->core.border_width * 2 +
- row->row.spacing * 2 ;
- if( preferred->height < h )
- {
- preferred->height = h ;
- }
- }
- }
- preferred->request_mode = CWWidth | CWHeight;
-
- /*
- * If both width and height are requested.
- */
- if( ( request->request_mode & CWWidth ) &&
- ( request->request_mode & CWHeight ) )
- {
- /*
- * If we are to be the same or bigger, say ok.
- */
- if( preferred->width <= request->width &&
- preferred->height <= request->height )
- {
- preferred->width = request->width;
- preferred->height = request->height;
- return( XtGeometryYes ) ;
- }
- /*
- * If both dimensions are unacceptable, say no.
- */
- else if( preferred->width < request->width &&
- preferred->height < request->height )
- {
- return( XtGeometryNo ) ;
- }
- /*
- * Otherwise one must be right, so say almost.
- */
- else
- {
- return( XtGeometryAlmost ) ;
- }
- }
- /*
- * If only the width is requested, either it's
- * OK or it isn't. Same for height.
- */
- else if( request->request_mode & CWWidth )
- {
- if( preferred->width <= request->width )
- {
- preferred->width = request->width ;
- return( XtGeometryYes ) ;
- }
- else
- {
- return( XtGeometryNo ) ;
- }
- }
- else if(request->request_mode & CWHeight)
- {
- if( preferred->height <= request->height )
- {
- preferred->height = request->height ;
- return( XtGeometryYes ) ;
- }
- else
- {
- return( XtGeometryNo ) ;
- }
- }
- return( XtGeometryYes ) ;
- }
-
-
-
- static XtGeometryResult
- GeometryManager(
- Widget w,
- XtWidgetGeometry *request,
- XtWidgetGeometry *reply
- )
- {
- XsRowWidget rw = (XsRowWidget)( w->core.parent ) ;
- Mask mask ;
- XtGeometryResult result ;
- Dimension wdelta ;
- Dimension hdelta ;
-
- /*
- * Say no. We control the vertical....
- */
- if( ( request->request_mode & CWX && request->x != w->core.x ) ||
- ( request->request_mode & CWY && request->y != w->core.y ) )
- {
- return( XtGeometryNo ) ;
- }
- /*
- * Otherwise, grant all requests if they fit.
- */
- if( request->request_mode & ( CWWidth | CWHeight | CWBorderWidth ) )
- {
- /*
- * Save the original widget size, and set the
- * corresponding widget fields to the requested sizes.
- */
- Dimension savewidth = w->core.width;
- Dimension saveheight = w->core.height;
- Dimension saveborderwidth = w->core.border_width;
-
- if( request->request_mode & CWWidth )
- {
- w->core.width = request->width ;
- }
- if( request->request_mode & CWHeight )
- {
- w->core.height = request->height ;
- }
- if( request->request_mode & CWBorderWidth )
- {
- w->core.border_width = request->border_width ;
- }
- /*
- * See if we can still handle all the children
- * if the request is granted.
- */
- result = try_layout( rw, &mask, &wdelta, &hdelta ) ;
- /*
- * If the children won't fit, restore the widget to its
- * original size, and return no.
- */
- if( result == XtGeometryNo )
- {
- w->core.width = savewidth ;
- w->core.height = saveheight ;
- w->core.border_width = saveborderwidth ;
- return( XtGeometryNo ) ;
- }
- /*
- * If only one dimension fits, restore the one that
- * doesn't fit and return "almost".
- */
- if( result == XtGeometryAlmost )
- {
- reply->request_mode = request->request_mode ;
- if( !( mask & CWWidth ) )
- {
- reply->width = w->core.width = savewidth ;
- reply->border_width = saveborderwidth ;
- w->core.border_width = saveborderwidth ;
- }
- if( !( mask & CWHeight ) )
- {
- reply->height = w->core.height = saveheight ;
- }
-
- return( XtGeometryAlmost ) ;
- }
- /*
- * If we got here, everything must fit, so reposition
- * all children based on the new size, and return "yes".
- */
- do_layout( rw ) ;
- return( XtGeometryYes ) ;
- }
- return( XtGeometryYes ) ;
- }
-
-
-
- static XtGeometryResult
- try_layout(
- XsRowWidget parent,
- Mask *mask,
- Dimension *w_delta,
- Dimension *h_delta
- )
- {
- int i ;
- Dimension total_width = 2 * parent->row.spacing ;
- Dimension max_height = 2 * parent->row.spacing ;
-
- /*
- * Get the bounding width and height of all children.
- */
- for( i = 0 ; i < parent->composite.num_children ; i++ )
- {
- Widget child ;
- Dimension width ;
- Dimension height ;
-
- child = parent->composite.children[i] ;
- if( child->core.managed )
- {
- height = child->core.height +
- child->core.border_width * 2 +
- parent->row.spacing * 2 ;
- width = child->core.width +
- child->core.border_width * 2 ;
- total_width += width ;
- max_height = MAX( max_height, height ) ;
- }
- }
- if( parent->composite.num_children > 1 )
- {
- total_width += ( parent->composite.num_children - 1 ) *
- parent->row.spacing ;
- }
-
- /*
- * If everyone doesn't fit, ask if we can grow. Return the
- * result, after setting the mask to indicate which (if
- * any) dimension is ok.
- */
- if( total_width > parent->core.width ||
- max_height > parent->core.height )
- {
- XtGeometryResult result ;
- Dimension replyWidth ;
- Dimension replyHeight ;
- Dimension width = MAX(total_width, parent->core.width);
- Dimension height = MAX(max_height, parent->core.height);
-
- result = XtMakeResizeRequest( (Widget)parent, width, height,
- &replyWidth, &replyHeight ) ;
- *mask = NULL ;
- if( total_width == replyWidth )
- {
- *mask = CWWidth ;
- }
- if( max_height == replyHeight )
- {
- *mask |= CWHeight ;
- }
-
- if( result == XtGeometryAlmost )
- {
- XtMakeResizeRequest( (Widget)parent, replyWidth,
- replyHeight, NULL, NULL) ;
- }
- *w_delta = total_width - parent->core.width;
- *h_delta = max_height - parent->core.height;
- return( result ) ;
- }
- /*
- * If everybody fits, just return yes.
- */
- *mask = CWWidth | CWHeight ;
- return( XtGeometryYes ) ;
- }
-
-
-
- static void
- ChangeManaged(
- Widget w
- )
- {
- XsRowWidget row = (XsRowWidget)w ;
- XtGeometryResult result;
- Dimension width, height, delta;
- int i;
- Mask mask;
- Widget child;
-
- /*
- * See if all children fit.
- */
- result = try_layout( row, &mask, &width, &height ) ;
-
- /*
- * Move all children to their new positions.
- */
- do_layout( row ) ;
- }
-
-